package src.cs2340.todoApp;

import java.util.ArrayList;
import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

/**
 * TaskListTest.java
 * CS 2340 M10
 * April 9, 2012
 * 
 * This is a TaskListTest for the sortByDate, sortByCategory, and getUncheckedTasks methods.
 */

public class TaskListTest {
	
	Location l1, l2, l3, l4, l5, home, school, work;
	Date d1, d2, d3, d4, d5, today, tomorrow;
	TaskItem t1, t2, t3, t4, t5, t6, t7, t8, t9;
	TaskList tA, tB, tC, tK;
	
	/**
	 * @author Kristian
	 * t1, t2, and t3 have the same category.  And I'm bringing back taskItems from
	 * CategoryComparatorTest.java.
	 * 
	 * make 2 taskLists one with t1-t5, second with t6-t9 for sortByDate
	 * 
	 * The third TaskList is for sortByCategory and will consist of t1, t2, t7, t8, and t9
	 * t1 and t2 are Personal, the other three are Work
	 * 
	 * The fourth TaskList has all the tasks and is for checking all unchecked tasks.
	 */
	@Before
	public void setUp() throws Exception {
		l1 = new Location("Fox Theatre", 141, "Fox Street", "Hollywood", "CA", 90210);
		d1 = new Date(12, 4, 2012, 6, 26, Date.Meredian.PM);
		//4-12-2012 6:26 PM
		t1 = new TaskItem("movies", l1, d1, "go to the movies", "Personal", false);
		
		l2 = new Location("Singapore", 26, "12th Street", "Singapore", "FL", 90002);
		d2 = new Date(17, 1, 2012, 6, 25, Date.Meredian.PM);
		t2 = new TaskItem("find magic sword", l2, d2, "go questing for epic magic " +
				"Sword of Thdsmwfiowjs", "Personal", false);
		
		l3 = new Location("Klinte Husgatan", 95, "3B Street", "Ystad", "SVE", 27144);
		//SVE is Sverige AKA Sweden.  In 95 3B Street, Ystad, Sverige + zip code.
		d3 = new Date(18, 12, 2011, 7, 17, Date.Meredian.PM);
		t3 = new TaskItem("attend birthday party", l3, d3, "It's your birthday! " +
				"It's your birthday! :D", "Personal", true);
		
		l4 = new Location("Linnegatan", 7, "Linnegatan Street", "Stockholm", "SVE", 11447);
		d4 = new Date(4, 5, 2015, 11, 12, Date.Meredian.AM);
		t4 = new TaskItem("Graduate.", l4, d4, "Go get your diploma", "School", false);
		
		
		Location l5 = new Location("Shrek's Swamp", 14, "Shrek Street", "Far Far Away", 
				"GA", 33333);
		Date d5 = new Date(13, 4, 2012, 1, 15, Date.Meredian.PM);
		t5 = new TaskItem("do M12", l5, d5, "have M12 done", "School", false);
		
		//and now to bring back old taskItems:
		home = new Location("home", 55, "Deville Drive", "Villa", "CA", 77233);
		today = new Date(2, 4, 2012, 4, 22, Date.Meredian.PM);//4:22PM 4-2-2012
		
		t6 = new TaskItem("play video games", home, today, "video games are fun! :D"
				, "Personal", false);
		
		school = new Location("GA Tech", 225, "North Avenue", "Atlanta", "GA", 30332);
		tomorrow = new Date(3, 4, 2012, 11, 11, Date.Meredian.AM);//11:11AM 4-3-2012
		
		t7 = new TaskItem("do m10", school, tomorrow, "why u no work?", 
				"Work", true);
		
		work = new Location("Heaven/Hell", 666777, "Crossroad of Pain and Pleasure", 
				"some place in Florida", "FL", 67888);
		
		t8 = new TaskItem("make video games", work, tomorrow, "make something cool!", 
				"Work", false);
		
		t9 = new TaskItem("make moar video games", work, tomorrow, "make moar kool stuff!", 
				"Work", true);
		
		//make 2 taskLists one with t1-t5, second with t6-t9 for sortByDate
		tA = new TaskList();
		tA.createTask(t1);
		tA.createTask(t2);
		tA.createTask(t3);
		tA.createTask(t4);
		tA.createTask(t5);
		
		tB = new TaskList();
		tB.createTask(t6);
		tB.createTask(t7);
		tB.createTask(t8);
		tB.createTask(t9);
		
		/* The third TaskList is for sortByCategory and will consist of t1, t2, t7, t8, and t9
		 * t1 and t2 are Personal, the other three are Work
		 */
		tC = new TaskList();
		tC.createTask(t1);
		tC.createTask(t2);
		tC.createTask(t7);
		tC.createTask(t8);
		tC.createTask(t9);
		
		tK = new TaskList();
		tK.createTask(t1);
		tK.createTask(t2);
		tK.createTask(t3);
		tK.createTask(t4);
		tK.createTask(t5);
		tK.createTask(t6);
		tK.createTask(t7);
		tK.createTask(t8);
		tK.createTask(t9);
	}
	
	/**
	 * @author Kristian
	 * This method will test if the TaskList has all the objects in order by Date.
	 * I will use ArrayList's get method to test if the TaskList is returning the
	 * correct taskItems for each index I call get.  This will violate the Law of
	 * Demeter, but it is for testing purposes.  It would seem redundant to make a 
	 * get method in TaskList just so I can avoid a double reference.
	 * 
	 * For the second TaskList, t7, t8, and t9 all occur on the same day, so we care only
	 * that t6 appears first, since it's the earliest task in that TaskList.
	 * 
	 * sortByDate - If it's later than the specified Date, then we add it.
	 * If it's earlier, we don't.
	 */
	@Test
	public void testSortByDate() {
		//are the taskItems at the specified indices equal to each instance of the taskItem?
		//before the sort?
		assertEquals("We haven't sorted the first TaskList yet.", (tA.getTasks()).get(0), t1);
		assertEquals("We haven't sorted the first TaskList yet.", (tA.getTasks()).get(1), t2);
		assertEquals("We haven't sorted the first TaskList yet.", (tA.getTasks()).get(2), t3);
		assertEquals("We haven't sorted the first TaskList yet.", (tA.getTasks()).get(3), t4);
		assertEquals("We haven't sorted the first TaskList yet.", (tA.getTasks()).get(4), t5);
		
		ArrayList<TaskItem> dateSorted1 = tA.sortByDate(d1);
		assertEquals("The task item on April 12, 2012 is the earliest one after sorting by " +
				"items occurring after April 12.  Expected: " + t1 + "but instead got: " + 
				dateSorted1.get(0), dateSorted1.get(0), t1);//t1, t5, t4
		
		assertEquals("Next comes the task on April 13, 2012. Expected: " + t5 + "but " +
				"instead got: " + dateSorted1.get(1), dateSorted1.get(1), t5);
		
		assertEquals("And then. Expected: " + t4 + "but instead got: " + dateSorted1.get(2),
				dateSorted1.get(2), t4);
		
		assertEquals("We haven't sorted the second TaskList yet.", (tB.getTasks()).get(0), t6);
		assertEquals("We haven't sorted the second TaskList yet.", (tB.getTasks()).get(1), t7);
		assertEquals("We haven't sorted the second TaskList yet.", (tB.getTasks()).get(2), t8);
		assertEquals("We haven't sorted the second TaskList yet.", (tB.getTasks()).get(3), t9);
		
		ArrayList<TaskItem> dateSorted2 = tA.sortByDate(d2);//t2, t1, t5, t4
		
		assertEquals("We want t2 first, since we're sorting by that date, and that is the " +
				"earliest one.  Was expecting: " + t2 + "but instead got: " + dateSorted2.get(0),
				dateSorted2.get(0), t2);
		
		assertEquals("Now the sort should work like t1. Expecting: " + t1 + "but got: " + 
				dateSorted2.get(1), dateSorted2.get(1), t1);
		
		assertEquals("Expecting: " + t5 + "but got" + dateSorted2.get(2), t5, dateSorted2.get(2));
		
		assertEquals("And lastly should be: " + t4 + "but got: " + dateSorted2.get(3), t4, 
				dateSorted2.get(3));
		
		ArrayList<TaskItem> dateSorted3 = tB.sortByDate(today);//t6, and the rest don't matter
		assertEquals("The last three tasks are on the same day, so we don't care what " +
				"order they are in.  We do care that the first taskItem is the first that comes" +
				"out.  Was expecting: " + t6 + "but instead got: " + dateSorted3.get(0), 
				dateSorted3.get(0), t6);
		
	}

	/**
	 * @author Kristian
	 * I will also use ArrayList's get method for testSortByCategory.  It will test 
	 * that the ArrayList contains objects of the same category, but has no other 
	 * members.  The size() method of ArrayList is also used.  Again, I am violating
	 * the Law of Demeter for testing purposes (see testSortByDate for why I'm doing this).
	 * 
	 * Basically, we're making sure there aren't tasks of other categories in a TaskList
	 * of a single category.
	 * 
	 * The third TaskList is for sortByCategory and will consist of t1, t2, t7, t8, and t9
     * t1 and t2 are Personal, the other three are Work
	 *
	 * sortByCategory - if it's of the specified category, we add it
	 * otherwise, we don't.
	 */
	@Test
	public void testSortByCategory() {
		ArrayList<TaskItem> categorizedList1 = tC.sortByCategory(0);//Personal
		assertEquals("Was expecting a task that was Personal" + t1.getCategory() + "not: " + 
				(categorizedList1.get(0)).getCategory(), t1.getCategory(), 
				(categorizedList1.get(0)).getCategory());
		
		assertEquals("Again, expecting: " + t2.getCategory() + "not: " + 
				(categorizedList1.get(1)).getCategory(), t2.getCategory(),
				(categorizedList1.get(1)).getCategory());
		
		
		ArrayList<TaskItem> categorizedList2 = tC.sortByCategory(2);//Work
		assertEquals("This time, I'm expecting a sort by Work, so no other categories, " + 
				"Personal belonged in the other list. Expected: " + t7.getCategory() + "not: " +
				(categorizedList2.get(0)).getCategory(), t7.getCategory(),
				(categorizedList2.get(0)).getCategory());
		
		assertEquals("Again, Work related tasks for this list. Expected: " + t8.getCategory()
				+ "not: " + (categorizedList2.get(1)).getCategory(), t8.getCategory(),
				(categorizedList2.get(1)).getCategory());
		
		assertEquals("Expecting: " + t9.getCategory() + "but actually got: " + 
				(categorizedList2.get(2)).getCategory(), t9.getCategory(), 
				(categorizedList2.get(2)).getCategory());
	} 

	/**
	 * @author Kristian
	 * The fourth TaskList has all the tasks and is for checking all unchecked tasks.
	 * We should have an arrayList for which every member has a checked value of false.
	 * Uses isChecked() from TaskItem class.
	 * 
	 * Since there are 6 taskItems with a checked value of false, the size should be 6, and 
	 * therefore, we check the size and that all 6 entries have a checked value of false, such
	 * that we know that t3, t7, and t9 are NOT in the ArrayList made from getUncheckedTasks().
	 */
	@Test
	public void testGetUncheckedTasks() {
		ArrayList<TaskItem> undone = tK.getUncheckedTasks();//t3, t7, and t9 should NOT be here.
		assertEquals("9 tasks - 3 unchecked tasks = 6 unchecked tasks.", undone.size(), 6);
		assertFalse((undone.get(0)).isChecked());
		assertFalse((undone.get(1)).isChecked());
		assertFalse((undone.get(2)).isChecked());
		assertFalse((undone.get(3)).isChecked());
		assertFalse((undone.get(4)).isChecked());
		assertFalse((undone.get(5)).isChecked());
	}
}
